/* Microsoft Reference Implementation for TPM 2.0
 *
 *  The copyright in this software is being made available under the BSD License,
 *  included below. This software may be subject to other third party and
 *  contributor rights, including patent rights, and no such rights are granted
 *  under this license.
 *
 *  Copyright (c) Microsoft Corporation
 *
 *  All rights reserved.
 *
 *  BSD License
 *
 *  Redistribution and use in source and binary forms, with or without modification,
 *  are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice, this list
 *  of conditions and the following disclaimer.
 *
 *  Redistributions in binary form must reproduce the above copyright notice, this
 *  list of conditions and the following disclaimer in the documentation and/or
 *  other materials provided with the distribution.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "Tpm.h"
#include "PolicyDuplicationSelect_fp.h"

#if CC_PolicyDuplicationSelect  // Conditional expansion of this file

/*(See part 3 specification)
// allows qualification of duplication so that it a specific new parent may be
// selected or a new parent selected for a specific object.
*/
//  Return Type: TPM_RC
//      TPM_RC_COMMAND_CODE   'commandCode' of 'policySession' is not empty
//      TPM_RC_CPHASH         'cpHash' of 'policySession' is not empty
/*
This command allows qualification of duplication to allow duplication to a selected new parent.
If this command not used in conjunction with a PolicyAuthorize Command, then only the new parent is selected and includeObject should be CLEAR.
EXAMPLE When an object is created when the list of allowed duplication targets is known, the policy would be created with includeObject CLEAR.

此命令允许对复制进行限定以允许复制到选定的新父代。
如果此命令未与 PolicyAuthorize 命令结合使用，则仅选择新的父代并且 includeObject 应为 CLEAR。
示例 如果在已知允许的复制目标列表的情况下创建对象，则将使用 includeObject CLEAR 创建策略。

NOTE 1 Only the new parent may be selected because, without TPM2_PolicyAuthorize(), the Name of the Object to be duplicated would 
need to be known at the time that Object's policy is created. However, since the Name of the Object includes its policy, the Name 
is not known. The Name can be known by the authorizing entity (a PolicyAuthorize Command) in which case includeObject may be SET.

注 1 只能选择新的父代，因为如果没有 TPM2_PolicyAuthorize()，在创建对象的策略时需要知道要复制的对象的名称。 但是，由于对象的名称包含其策略，
因此名称是未知的。 授权实体（PolicyAuthorize 命令）可以知道名称，在这种情况下可以设置 includeObject。

待迁移对象的名称保护其策略，但是创建对象的策略时又需要知道复制的对象的名称，所以按照正常方式，无法确定该对象的名称。
但是可以使用授权实体命令（PolicyAuthorize）来预先创建该对象，以确定其名称。TODO: 具体如何使用？

If used in conjunction with TPM2_PolicyAuthorize(), then the authorizer of the new policy has the option of selecting just the 
new parent or of selecting both the new parent and the duplication Object.
如果与 TPM2_PolicyAuthorize() 一起使用，那么新策略的授权者可以选择只选择新的父对象或同时选择新的父对象和复制对象。


*/
TPM_RC
TPM2_PolicyDuplicationSelect(
    PolicyDuplicationSelect_In  *in             // IN: input parameter list
    )
{
    SESSION         *session;
    HASH_STATE      hashState;
    TPM_CC          commandCode = TPM_CC_PolicyDuplicationSelect;

// Input Validation

    // Get pointer to the session structure
    session = SessionGet(in->policySession);

    // cpHash in session context must be empty
    if(session->u1.cpHash.t.size != 0)
        return TPM_RC_CPHASH;

    // commandCode in session context must be empty
    if(session->commandCode != 0)
        return TPM_RC_COMMAND_CODE;

// Internal Data Update

    // Update name hash
    session->u1.cpHash.t.size = CryptHashStart(&hashState, session->authHashAlg);

    //  add objectName
    CryptDigestUpdate2B(&hashState, &in->objectName.b);

    //  add new parent name
    CryptDigestUpdate2B(&hashState, &in->newParentName.b);

    //  complete hash
    CryptHashEnd2B(&hashState, &session->u1.cpHash.b);

    // update policy hash
    // Old policyDigest size should be the same as the new policyDigest size since
    // they are using the same hash algorithm
    session->u2.policyDigest.t.size
        = CryptHashStart(&hashState, session->authHashAlg);
//  add old policy
    CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b);

    //  add command code
    CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode);

    //  add objectName
    // 确定是否要绑定待迁移的对象的名称
    if(in->includeObject == YES)
        CryptDigestUpdate2B(&hashState, &in->objectName.b);

    //  add new parent name
    CryptDigestUpdate2B(&hashState, &in->newParentName.b);

    //  add includeObject
    CryptDigestUpdateInt(&hashState, sizeof(TPMI_YES_NO), in->includeObject);

    //  complete digest
    CryptHashEnd2B(&hashState, &session->u2.policyDigest.b);

    // set commandCode in session context
    session->commandCode = TPM_CC_Duplicate;

    return TPM_RC_SUCCESS;
}

#endif // CC_PolicyDuplicationSelect